using System;
using System.Collections.Generic;
using Holoville.HOTween;
using UnityEngine;

[RequireComponent(typeof(BoxCollider))]
public class ScrollView : MonoBehaviour
{
	private void Awake()
	{
		if (this.itemRoot.transform.parent != base.transform)
		{
			UnityEngine.Debug.LogWarning("Item Root's Parent must be ScrollView!!!");
		}
		if (this.itemRoot.transform.localScale != Vector3.one)
		{
			UnityEngine.Debug.LogWarning("Item Root's LocalScale must be Vector3.one!!!");
		}
		foreach (GameObject gameObject in this.items)
		{
			if (gameObject.transform.parent != this.itemRoot.transform)
			{
				UnityEngine.Debug.LogWarning("Scroll Items Root's Parent must be ItemRoot!!!");
			}
		}
		if (null == this.viewCamera)
		{
			this.viewCamera = Camera.main;
		}
		this.initPosition = this.itemRoot.transform.localPosition;
	}

	private void Start()
	{
		this.SetScrollIndex(this.currentIndex, 0f);
	}

	public int GetScrollIndex()
	{
		return this.currentIndex;
	}

	public void SetScrollIndex(int index, float time = 0f)
	{
		float num = 0f;
		HOTween.Complete(this.itemRoot.transform);
		index = Mathf.Min(this.items.Count - 1, index);
		if (this.GetScrollIndex() != index)
		{
			if (this.targetObject && this.messageScroll != null && this.messageScroll != string.Empty)
			{
				this.targetObject.SendMessage(this.messageScroll, base.gameObject);
			}
			if (this.onScroll != null)
			{
				this.onScroll(this);
			}
		}
		this.currentIndex = index;
		this.targetIndex = index;
		if (this.items.Count <= 0 || this.items.Count <= this.currentIndex)
		{
			return;
		}
		Vector3 b = new Vector3(0f, 0f, 0f);
		if (this.haveExpendSlot)
		{
			b = new Vector3(0f, -2f, 0f);
		}
		Vector3 vector = this.itemRoot.transform.position - this.items[this.currentIndex].transform.position + this.initPosition + b;
		if ((vector.y > 10f || index >= 1) && vector.x >= 0f)
		{
			num = 1f;
		}
		Vector3 vector2 = new Vector3(vector.x, vector.y + num, vector.z);
		if (time <= 0f)
		{
			this.itemRoot.transform.localPosition = vector2;
			this.ScrollEnd();
		}
		else
		{
			HOTween.To(this.itemRoot.transform, time, new TweenParms().Prop("localPosition", vector2).Ease(EaseType.EaseInOutCubic).OnComplete(delegate()
			{
				this.ScrollEnd();
			}));
		}
	}

	private void ScrollEnd()
	{
		if (this.targetObject && this.messageScrollEnd != null && this.messageScrollEnd != string.Empty)
		{
			this.targetObject.SendMessage(this.messageScrollEnd, base.gameObject);
		}
		if (this.onScrollEnd != null)
		{
			this.onScrollEnd(this);
		}
	}

	private void Update()
	{
		if (Time.timeScale == 0f)
		{
			return;
		}
		if (Time.deltaTime == 0f)
		{
			return;
		}
		if (!this.viewCamera.gameObject.activeSelf || !this.viewCamera.enabled)
		{
			return;
		}
		if (!base.GetComponent<Collider>().enabled)
		{
			return;
		}
		if (Input.GetMouseButtonDown(0) && !this.buttonDown)
		{
			this.buttonDown = true;
			this.OnMouseButtonDown();
		}
		if (Input.GetMouseButton(0) && !Input.GetMouseButtonUp(0) && this.buttonDown)
		{
			this.OnMouseButtonPress();
		}
		if (Input.GetMouseButtonUp(0) && this.buttonDown)
		{
			this.buttonDown = false;
			this.OnMouseButtonUp();
		}
	}

	private void OnMouseButtonDown()
	{
		Ray ray = this.viewCamera.ScreenPointToRay(UnityEngine.Input.mousePosition);
		RaycastHit raycastHit;
		if (!Physics.Raycast(ray, out raycastHit) || raycastHit.collider != base.GetComponent<Collider>())
		{
			return;
		}
		HOTween.Complete(this.itemRoot.transform);
		this.marginLock = true;
		this.downPosition = this.viewCamera.ScreenToWorldPoint(UnityEngine.Input.mousePosition);
		this.rootPosition = this.itemRoot.transform.localPosition;
		if (this.targetObject && this.messageScrollBegin != null && this.messageScrollBegin != string.Empty)
		{
			this.targetObject.SendMessage(this.messageScrollBegin, base.gameObject);
		}
		if (this.onScrollBegin != null)
		{
			this.onScrollBegin(this);
		}
	}

	private void OnMouseButtonPress()
	{
		Ray ray = this.viewCamera.ScreenPointToRay(UnityEngine.Input.mousePosition);
		RaycastHit raycastHit;
		if (!Physics.Raycast(ray, out raycastHit) || raycastHit.collider != base.GetComponent<Collider>())
		{
			return;
		}
		Vector3 vector = this.viewCamera.ScreenToWorldPoint(UnityEngine.Input.mousePosition);
		this.currentPosition = vector;
		Vector3 vector2 = (this.currentPosition - this.downPosition) * this.scrollSensitivity;
		vector2.z = 0f;
		if (vector2 == Vector3.zero)
		{
			return;
		}
		if (vector2.magnitude > this.margin)
		{
			if (this.marginLock)
			{
				if (this.targetObject && this.messageScroll != null && this.messageScroll != string.Empty)
				{
					this.targetObject.SendMessage(this.messageScroll, base.gameObject);
				}
				if (this.onScroll != null)
				{
					this.onScroll(this);
				}
			}
			this.marginLock = false;
		}
		if (this.marginLock)
		{
			return;
		}
		if (this.items.Count <= 0)
		{
			return;
		}
		this.currentIndex = Mathf.Min(this.items.Count - 1, this.currentIndex);
		GameObject gameObject = this.items[this.currentIndex];
		if (this.items.Count > 1)
		{
			if (this.currentIndex == 0)
			{
				this.targetIndex = 1;
			}
			else if (this.currentIndex == this.items.Count - 1)
			{
				this.targetIndex = this.items.Count - 2;
			}
			else
			{
				GameObject gameObject2 = this.items[this.currentIndex - 1];
				GameObject gameObject3 = this.items[this.currentIndex + 1];
				Vector3 a = gameObject2.transform.localPosition - gameObject.transform.localPosition;
				Vector3 a2 = gameObject3.transform.localPosition - gameObject.transform.localPosition;
				Vector3 vector3 = a / a.magnitude + vector2 / vector2.magnitude;
				if ((a2 / a2.magnitude + vector2 / vector2.magnitude).sqrMagnitude > vector3.sqrMagnitude)
				{
					this.targetIndex = this.currentIndex - 1;
				}
				else
				{
					this.targetIndex = this.currentIndex + 1;
				}
			}
		}
		Vector3 a3 = new Vector3(this.defaultDirection.x, this.defaultDirection.y, 0f);
		float num = a3.x * vector2.x + a3.y * vector2.y + a3.z * vector2.z;
		if (num > 0f)
		{
			a3 *= -1f;
		}
		if (this.currentIndex != this.targetIndex)
		{
			GameObject gameObject4 = this.items[this.targetIndex];
			a3 = gameObject.transform.localPosition - gameObject4.transform.localPosition;
		}
		Vector3 normalized = a3.normalized;
		Vector3 normalized2 = vector2.normalized;
		num = normalized.x * normalized2.x + normalized.y * normalized2.y + normalized.z * normalized2.z;
		if (Mathf.Abs(num) < 0.5f)
		{
			return;
		}
		if (num < 0f)
		{
			num *= 0.5f;
		}
		this.itemRoot.transform.localPosition = a3 / a3.magnitude * num * vector2.magnitude + this.rootPosition;
		if (a3.sqrMagnitude < vector2.sqrMagnitude && num > 0f)
		{
			this.SetScrollIndex(this.targetIndex, 0f);
			this.downPosition = vector;
			this.rootPosition = this.itemRoot.transform.localPosition;
		}
	}

	private void OnMouseButtonUp()
	{
		if (this.items.Count <= 0)
		{
			return;
		}
		int index = this.currentIndex;
		GameObject gameObject = this.items[this.currentIndex];
		GameObject gameObject2 = this.items[this.targetIndex];
		Vector3 vector = gameObject.transform.localPosition - gameObject2.transform.localPosition;
		Vector3 vector2 = (this.currentPosition - this.downPosition) * this.scrollSensitivity;
		float num = vector.x * vector2.x + vector.y * vector2.y + vector.z * vector2.z;
		if (num > 0f && vector2.magnitude > vector.magnitude * this.bounceBackRate)
		{
			index = this.targetIndex;
		}
		float time = 0f;
		if (this.bounceBackSpeed > 0f)
		{
			time = Mathf.Sqrt((this.itemRoot.transform.localPosition - this.initPosition + this.items[index].transform.localPosition).magnitude) / this.bounceBackSpeed;
		}
		this.SetScrollIndex(index, time);
	}

	public Camera viewCamera;

	public bool haveExpendSlot;

	public GameObject itemRoot;

	public List<GameObject> items;

	public float margin;

	[NonSerialized]
	public bool marginLock = true;

	public float scrollSensitivity = 1f;

	public float bounceBackSpeed = 1f;

	public float bounceBackRate = 0.25f;

	public Vector2 defaultDirection = Vector2.right;

	public GameObject targetObject;

	public string messageScrollBegin = string.Empty;

	public string messageScroll = string.Empty;

	public string messageScrollEnd = string.Empty;

	public Action<ScrollView> onScrollBegin;

	public Action<ScrollView> onScroll;

	public Action<ScrollView> onScrollEnd;

	private int currentIndex;

	private int targetIndex;

	private Vector3 initPosition = Vector3.zero;

	private Vector3 rootPosition = Vector3.zero;

	private Vector3 downPosition = Vector3.zero;

	private Vector3 currentPosition = Vector3.zero;

	private bool buttonDown;
}
